7c59169720ca6ba0facb258689e06f55f0176855
[openwrt/openwrt.git] /
1 From cf27d9475f37fb69b5bc293e6e6d6c1d03cf7cc6 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Stephan=20M=C3=BCller?= <smueller@chronox.de>
3 Date: Thu, 19 Oct 2023 09:40:42 +0200
4 Subject: [PATCH] crypto: jitter - use permanent health test storage
5
6 The health test result in the current code is only given for the currently
7 processed raw time stamp. This implies to react on the health test error,
8 the result must be checked after each raw time stamp being processed. To
9 avoid this constant checking requirement, any health test error is recorded
10 and stored to be analyzed at a later time, if needed.
11
12 This change ensures that the power-up test catches any health test error.
13 Without that patch, the power-up health test result is not enforced.
14
15 The introduced changes are already in use with the user space version of
16 the Jitter RNG.
17
18 Fixes: 04597c8dd6c4 ("jitter - add RCT/APT support for different OSRs")
19 Reported-by: Joachim Vandersmissen <git@jvdsn.com>
20 Signed-off-by: Stephan Mueller <smueller@chronox.de>
21 Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
22 ---
23 crypto/jitterentropy.c | 125 ++++++++++++++++++++++++-----------------
24 1 file changed, 74 insertions(+), 51 deletions(-)
25
26 --- a/crypto/jitterentropy.c
27 +++ b/crypto/jitterentropy.c
28 @@ -100,6 +100,8 @@ struct rand_data {
29 unsigned int apt_observations; /* Number of collected observations */
30 unsigned int apt_count; /* APT counter */
31 unsigned int apt_base; /* APT base reference */
32 + unsigned int health_failure; /* Record health failure */
33 +
34 unsigned int apt_base_set:1; /* APT base reference set? */
35 };
36
37 @@ -121,6 +123,13 @@ struct rand_data {
38 #define JENT_EHASH 11 /* Hash self test failed */
39 #define JENT_EMEM 12 /* Can't allocate memory for initialization */
40
41 +#define JENT_RCT_FAILURE 1 /* Failure in RCT health test. */
42 +#define JENT_APT_FAILURE 2 /* Failure in APT health test. */
43 +#define JENT_PERMANENT_FAILURE_SHIFT 16
44 +#define JENT_PERMANENT_FAILURE(x) (x << JENT_PERMANENT_FAILURE_SHIFT)
45 +#define JENT_RCT_FAILURE_PERMANENT JENT_PERMANENT_FAILURE(JENT_RCT_FAILURE)
46 +#define JENT_APT_FAILURE_PERMANENT JENT_PERMANENT_FAILURE(JENT_APT_FAILURE)
47 +
48 /*
49 * The output n bits can receive more than n bits of min entropy, of course,
50 * but the fixed output of the conditioning function can only asymptotically
51 @@ -215,26 +224,22 @@ static void jent_apt_insert(struct rand_
52 return;
53 }
54
55 - if (delta_masked == ec->apt_base)
56 + if (delta_masked == ec->apt_base) {
57 ec->apt_count++;
58
59 + /* Note, ec->apt_count starts with one. */
60 + if (ec->apt_count >= ec->apt_cutoff_permanent)
61 + ec->health_failure |= JENT_APT_FAILURE_PERMANENT;
62 + else if (ec->apt_count >= ec->apt_cutoff)
63 + ec->health_failure |= JENT_APT_FAILURE;
64 + }
65 +
66 ec->apt_observations++;
67
68 if (ec->apt_observations >= JENT_APT_WINDOW_SIZE)
69 jent_apt_reset(ec, delta_masked);
70 }
71
72 -/* APT health test failure detection */
73 -static int jent_apt_permanent_failure(struct rand_data *ec)
74 -{
75 - return (ec->apt_count >= ec->apt_cutoff_permanent) ? 1 : 0;
76 -}
77 -
78 -static int jent_apt_failure(struct rand_data *ec)
79 -{
80 - return (ec->apt_count >= ec->apt_cutoff) ? 1 : 0;
81 -}
82 -
83 /***************************************************************************
84 * Stuck Test and its use as Repetition Count Test
85 *
86 @@ -261,6 +266,30 @@ static void jent_rct_insert(struct rand_
87 {
88 if (stuck) {
89 ec->rct_count++;
90 +
91 + /*
92 + * The cutoff value is based on the following consideration:
93 + * alpha = 2^-30 or 2^-60 as recommended in SP800-90B.
94 + * In addition, we require an entropy value H of 1/osr as this
95 + * is the minimum entropy required to provide full entropy.
96 + * Note, we collect (DATA_SIZE_BITS + ENTROPY_SAFETY_FACTOR)*osr
97 + * deltas for inserting them into the entropy pool which should
98 + * then have (close to) DATA_SIZE_BITS bits of entropy in the
99 + * conditioned output.
100 + *
101 + * Note, ec->rct_count (which equals to value B in the pseudo
102 + * code of SP800-90B section 4.4.1) starts with zero. Hence
103 + * we need to subtract one from the cutoff value as calculated
104 + * following SP800-90B. Thus C = ceil(-log_2(alpha)/H) = 30*osr
105 + * or 60*osr.
106 + */
107 + if ((unsigned int)ec->rct_count >= (60 * ec->osr)) {
108 + ec->rct_count = -1;
109 + ec->health_failure |= JENT_RCT_FAILURE_PERMANENT;
110 + } else if ((unsigned int)ec->rct_count >= (30 * ec->osr)) {
111 + ec->rct_count = -1;
112 + ec->health_failure |= JENT_RCT_FAILURE;
113 + }
114 } else {
115 /* Reset RCT */
116 ec->rct_count = 0;
117 @@ -316,38 +345,24 @@ static int jent_stuck(struct rand_data *
118 }
119
120 /*
121 - * The cutoff value is based on the following consideration:
122 - * alpha = 2^-30 or 2^-60 as recommended in SP800-90B.
123 - * In addition, we require an entropy value H of 1/osr as this is the minimum
124 - * entropy required to provide full entropy.
125 - * Note, we collect (DATA_SIZE_BITS + ENTROPY_SAFETY_FACTOR)*osr deltas for
126 - * inserting them into the entropy pool which should then have (close to)
127 - * DATA_SIZE_BITS bits of entropy in the conditioned output.
128 + * Report any health test failures
129 *
130 - * Note, ec->rct_count (which equals to value B in the pseudo code of SP800-90B
131 - * section 4.4.1) starts with zero. Hence we need to subtract one from the
132 - * cutoff value as calculated following SP800-90B. Thus
133 - * C = ceil(-log_2(alpha)/H) = 30*osr or 60*osr.
134 - */
135 -static int jent_rct_permanent_failure(struct rand_data *ec)
136 -{
137 - return (ec->rct_count >= (60 * ec->osr)) ? 1 : 0;
138 -}
139 -
140 -static int jent_rct_failure(struct rand_data *ec)
141 -{
142 - return (ec->rct_count >= (30 * ec->osr)) ? 1 : 0;
143 -}
144 -
145 -/* Report of health test failures */
146 -static int jent_health_failure(struct rand_data *ec)
147 -{
148 - return jent_rct_failure(ec) | jent_apt_failure(ec);
149 -}
150 + * @ec [in] Reference to entropy collector
151 + *
152 + * @return a bitmask indicating which tests failed
153 + * 0 No health test failure
154 + * 1 RCT failure
155 + * 2 APT failure
156 + * 1<<JENT_PERMANENT_FAILURE_SHIFT RCT permanent failure
157 + * 2<<JENT_PERMANENT_FAILURE_SHIFT APT permanent failure
158 + */
159 +static unsigned int jent_health_failure(struct rand_data *ec)
160 +{
161 + /* Test is only enabled in FIPS mode */
162 + if (!fips_enabled)
163 + return 0;
164
165 -static int jent_permanent_health_failure(struct rand_data *ec)
166 -{
167 - return jent_rct_permanent_failure(ec) | jent_apt_permanent_failure(ec);
168 + return ec->health_failure;
169 }
170
171 /***************************************************************************
172 @@ -594,11 +609,12 @@ int jent_read_entropy(struct rand_data *
173 return -1;
174
175 while (len > 0) {
176 - unsigned int tocopy;
177 + unsigned int tocopy, health_test_result;
178
179 jent_gen_entropy(ec);
180
181 - if (jent_permanent_health_failure(ec)) {
182 + health_test_result = jent_health_failure(ec);
183 + if (health_test_result > JENT_PERMANENT_FAILURE_SHIFT) {
184 /*
185 * At this point, the Jitter RNG instance is considered
186 * as a failed instance. There is no rerun of the
187 @@ -606,13 +622,18 @@ int jent_read_entropy(struct rand_data *
188 * is assumed to not further use this instance.
189 */
190 return -3;
191 - } else if (jent_health_failure(ec)) {
192 + } else if (health_test_result) {
193 /*
194 * Perform startup health tests and return permanent
195 * error if it fails.
196 */
197 - if (jent_entropy_init(0, 0, NULL, ec))
198 + if (jent_entropy_init(0, 0, NULL, ec)) {
199 + /* Mark the permanent error */
200 + ec->health_failure &=
201 + JENT_RCT_FAILURE_PERMANENT |
202 + JENT_APT_FAILURE_PERMANENT;
203 return -3;
204 + }
205
206 return -2;
207 }
208 @@ -695,6 +716,7 @@ int jent_entropy_init(unsigned int osr,
209 */
210 struct rand_data *ec = p_ec;
211 int i, time_backwards = 0, ret = 0, ec_free = 0;
212 + unsigned int health_test_result;
213
214 if (!ec) {
215 ec = jent_entropy_collector_alloc(osr, flags, hash_state);
216 @@ -708,6 +730,9 @@ int jent_entropy_init(unsigned int osr,
217 ec->apt_base_set = 0;
218 /* Reset the RCT */
219 ec->rct_count = 0;
220 + /* Reset intermittent, leave permanent health test result */
221 + ec->health_failure &= (~JENT_RCT_FAILURE);
222 + ec->health_failure &= (~JENT_APT_FAILURE);
223 }
224
225 /* We could perform statistical tests here, but the problem is
226 @@ -788,12 +813,10 @@ int jent_entropy_init(unsigned int osr,
227 }
228
229 /* Did we encounter a health test failure? */
230 - if (jent_rct_failure(ec)) {
231 - ret = JENT_ERCT;
232 - goto out;
233 - }
234 - if (jent_apt_failure(ec)) {
235 - ret = JENT_EHEALTH;
236 + health_test_result = jent_health_failure(ec);
237 + if (health_test_result) {
238 + ret = (health_test_result & JENT_RCT_FAILURE) ? JENT_ERCT :
239 + JENT_EHEALTH;
240 goto out;
241 }
242